24. 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

1652182790139

输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例2:

输入:head = []
输出:[]

示例3:

输入:head = [1]
输出:[1]

算法思路:

定义四个指针,p,pre,t,res,让 t 每次指向 p 的 后 一个,pre 指向 p 的前一个,res 用来记住新链表的头,通过 flag 标志实现 让 res 只记录第一次 t 的值(因为 t 会变)。如果 t 为空,说明到尾部,无法交换,直接结束。t.next = pre; 让 t 下一个指向其前一个,而 pre 的 下一个指向分两种情况

  • p 为 null,直接为 null
  • p 不为 null 时分两种情况(此时总节点数大于 1):
    • 总结点数为奇数 ( p.next == null ) 让 pre 下一个指向 p
    • 总结点数为偶数 ( p.next != null ) 让 pre下一个指向 p.next

代码实现:

public class Q0024SwapNodesInPairs {
    public static void main(String[] args) {
        Solution solution = new Q0024SwapNodesInPairs().new Solution();
        int[] nums = {1,2,3,4,5,6,7};
        ListNode listNode = ListNode.create(nums);
        ListNode.print(listNode);
        ListNode listNode1 = solution.swapPairs(listNode);
        ListNode.print(listNode1);
    }

    class Solution {
        public ListNode swapPairs(ListNode head) {
            ListNode p = head, pre, t, res = null;
            // 用来记录新链表的头
            boolean flag = true;
            while (p != null) {
                t = p.next;
                pre = p;
                // 只记录为第一次
                if (flag) res = t;
                if (t == null) break;
                flag = false;
                p = t.next;
                t.next = pre;
                // p 不为 null 时分两种情况(节点数大于 1):
                // 1.结点数为奇数 (p.next == null)  让 pre下一个指向 p
                // 2.结点数为偶数 (p.next != null)  让 pre下一个指向 p.next
                pre.next = p == null ? null : p.next == null ? p : p.next;
            }
            // 如果 res 为空说明只有一个结点直接返回原链表
            return res == null ? head : res;
        }
    }

}

Q.E.D.


以无限为有限,以无法为有法