链表问题----将单向链表按某值划分成左边小、中间相等、右边大的形式
将单向链表按某值划分成左边小、中间相等、右边大的形式
给定一个单向链表的头节点head,节点的值类型是整数,再给定一个整数 pivot,实现一个调整链表的函数,使得左半部分的值都是小于pivot的节点,中间部分都是等于pivot的节点,右边部分都是大于pivot的节点,对于左半部分、中间、右半部分内部的顺序没有要求。
如果对于三部分内部的顺序也是有要求,即内部顺序各个节点的顺序与原来链表中的各个节点的先后顺序相同。
【解析】
普通问题:
首先遍历一遍链表,得到链表的长度,将链表元素依次放到数组中,然后利用类似于快速排序中的partition 思想进行分割。
进阶问题:
1.将链表分为三部分:small,equal,big
small:1->2->null
equal:5->5->null
big:9->8->null
2.将small、equal、big三个链表重新串起来
3.整个过程需要特别注意对null节点的判断和处理
package com.test; import com.test.ListNode; /** * Created by Demrystv. */ public class ListNodePartition { /** * 普通问题 * 时间复杂度是 O(N),空间复杂度是 O(N) */ /* 首先遍历一遍链表,得到链表的长度,将链表元素依次放到数组中,然后利用类似于快速排序中的partition 思想进行分割 */ public ListNode listPartition1(ListNode head, int pivot){ if (head == null){ return head; } int i = 0; ListNode cur = head; while (cur != null){ i++; cur = cur.next; } // 将链表中的每个元素依次放入到数组中 ListNode[] nodeArr = new ListNode[i]; i = 0; cur = head; for (i = 0; i != nodeArr.length; i++){ nodeArr[i] = cur; cur = cur.next; } // 进行类似快速排序的partition arrPartition(nodeArr,pivot); // 重新连接各个链表节点 for (i = 1; i != nodeArr.length; i++){ nodeArr[i - 1].next = nodeArr[i]; } nodeArr[i - 1].next = null; return nodeArr[0]; } public void arrPartition(ListNode[] nodeArr, int pivot){ int small = -1; int big = nodeArr.length; int index = 0; while (index != big){ if (nodeArr[index].val < pivot){ swap(nodeArr, ++small, index); }else if (nodeArr[index].val == pivot){ index++; }else { swap(nodeArr, --big, index); } } } public void swap(ListNode[] nodeArr, int a, int b){ ListNode temp = nodeArr[a]; nodeArr[a] = nodeArr[b]; nodeArr[b] = temp; } /** * 进阶问题: 保证各部分内部的顺序与原来链表中各个节点的顺序相同 * 时间复杂度是 O(N),空间复杂度是 O(1) * 考察 利用有限的几个变量来调整链表的代码实现能力。 */ /* 1.将链表分为三部分:small,equal,big small:1->2->null equal:5->5->null big:9->8->null 2.将small、equal、big三个链表重新串起来 3.整个过程需要特别注意对null节点的判断和处理 */ public ListNode listPartition2(ListNode head, int pivot){ // 将链表分为small、equal、big ListNode sH = null; ListNode sT = null; ListNode eH = null; ListNode eT = null; ListNode bH = null; ListNode bT = null; ListNode next = null;// 保存下一个节点 //将所有的节点依次保存在三个链表中 while (head != null){ // 将head节点独立出来 next = head.next; head.next = null; if (head.val < pivot){ if (sH == null){ sH = head; sT = head; }else { sT.next = head; sT = head; } }else if (head.val == 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; } }