题目一:
编写代码,以给定值x为基准将链表分为两部分,所有小于x的结点排在大于或等于x的结点之前。给定一个链表的头结点 ListNode * pHead,请返回重新后的链表的头指针。注意:分割以后原来的数据顺序不变,不要开辟新的空间,即不要新建节点。比如 5 6 3 2 7 以 3 为基准分区后为2 5 6 3 7。
思路:题目说不要新建节点,但是可以新建节点指针。定义左右两个链表指针,小于x的元素链接到左边链表,大于等于x的元素链接到右边链表,最后左右两个链表相连即可。这里需要注意边界的问题,假如左边的链表为空,那么直接返回右边链表的头指针。
1 public class 链表分区 { 2 private static class ListNode { 3 int val; 4 ListNode next = null; 5 6 ListNode(int val) { 7 this.val = val; 8 } 9 10 @Override 11 public String toString() { 12 StringBuilder sb = new StringBuilder(val + ""); 13 ListNode nnext = next; 14 while (nnext != null) { 15 sb.append(nnext.val); 16 nnext = nnext.next; 17 } 18 return sb.toString(); 19 } 20 } 21 public static ListNode partition(ListNode pHead, int x) { 22 ListNode p = pHead; 23 ListNode leftFirst = null; 24 ListNode leftTail = null; 25 ListNode rightFirst = null; 26 ListNode rightTail = null; 27 28 while (p != null) {//顺序扫描所有节点 29 int pValue = p.val; 30 if (pValue < x) {//小于x 31 if (leftTail == null) { 32 leftFirst = p; 33 leftTail = p; 34 } else { 35 leftTail.next = p; 36 leftTail = leftTail.next; 37 } 38 } else {//大于等于x 39 if (rightTail == null) { 40 rightFirst = p; 41 rightTail = p; 42 } else { 43 rightTail.next = p; 44 rightTail = rightTail.next; 45 } 46 } 47 p = p.next; 48 } 49 if (leftFirst == null) {// 左边链表可能为空 50 return rightFirst; 51 } 52 leftTail.next = rightFirst;//左右两个链表连接起来 53 if (rightTail != null) 54 rightTail.next = null; 55 return leftFirst; 56 } 57 public static void main(String[] args) { 58 int[] arr = { 5,6,3,2,7 }; 59 ListNode head = new ListNode(arr[0]);// 哑元 60 ListNode p = head; 61 for (int i = 1; i < arr.length; i++) { 62 p.next = new ListNode(arr[i]); 63 p = p.next; 64 } 65 ListNode p1 = head.next; 66 ListNode res = partition(head, 3); 67 while (res != null) { 68 // 理解这里为什么通过res就能遍历链表 函数里是左右链表连接起来的 69 System.out.println(res.val); 70 res = res.next; 71 } 72 } 73 }