
 给出一个单向链表,第i 个node 和 第(n-1-i)个node称为twin.
 0 <= i <= n/2 - 1
 求所有twin的最大和。
 链表长度为偶数。
思路:
链表长度为偶数,就省了不少步骤,不用再考虑奇数时中间那个node单独计算了。
 直觉上来看,应该是先走到链表的中间位置,然后从中间到两边两两值求和,取最大的。
后半部分往结尾走还比较简单,那如何从中间往head处走呢?
或许会想到用一个数组保存链表所有的值,然后用数组下标访问元素。
 那么就需要先遍历一遍链表,再额外需要一个长度为n的数组,这里不用这种方法。
再说如何让指针从中间往head处走。
 因为是单向链表,没有回头指针,肯定是行不通的。
 但是,可以把前半部分逆序。
 逆序了,就可以正常地从head走到中间。
怎么确定只逆序前半部分,何时停止?
 以前都是用快慢指针来确定链表一半的位置,这里不需要慢指针,只需要快指针,
 只要快指针到了终点,就停止逆序过程。
来模拟一下这个过程,用Example1的数据。
 先不考虑只逆序一半,先看看如何实现逆序排列。
 申请一个新指针newHead, 方便操作。
 newHead -> 5 -> 4 -> 2 -> 1
用head指针指向当前node, post指针指向下一node,
 那么这时候head指向5,post指向4,
 把post换到newHead后面,就变成
 newHead -> 4 -> 5 -> 2 -> 1
这时post还是指向4,head指向5,把post指向head.next, 也就是2,
 再把post换到newHead后面,变成
 newHead -> 2 -> 4 -> 5 -> 1
head还是指向5,再把post指向head.next, 也就是1
 把post换到newHead后面,变成
 newHead -> 1 -> 2 -> 4 -> 5
这样就实现了逆序排列,只需要在快指针变成null时停止,就实现了只对前半部分逆序。
 你说中间交换指针会不会影响快指针的位置?
 不会,因为交换4到newHead后面时,快指针已经走到2了,交换的位置追不上快指针的位置。
快指针变成null时,链表变成
 newHead -> 4 -> 5 -> 2 -> 1
这时head指向5,post指向4,
 现在把post指向head.next, 也就是2,
 把head移动到newHead.next, 也就是开头的4,
 现在每次head和post都向后移动一步,直到post为null,
 找到head.val + post.val的最大值即可。
public int pairSum(ListNode head) {
    ListNode newHead = new ListNode();
    newHead.next = head;
    ListNode fast = head;
    ListNode post = head.next;
    int res = 0;
    //链表前半部分逆序排列
    while(fast != null && fast.next != null) {
        fast = fast.next.next;
        if(fast == null) break;
        
        //swap post node to newHead.next
        head.next = post.next;
        post.next = newHead.next;
        newHead.next = post;
        post = head.next;
    }
    head = newHead.next;
    while(post != null) {
        res = Math.max(res, post.val + head.val);
        head = head.next;
        post = post.next;
    }
    return res;
}
 




















