[LeetCode] 24. 两两交换链表中的节点

时间:2019-09-28
本文章向大家介绍[LeetCode] 24. 两两交换链表中的节点,主要包括[LeetCode] 24. 两两交换链表中的节点使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

传送门:[LeetCode] 24. 两两交换链表中的节点

题目描述

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 :

给定 1->2->3->4, 你应该返回 2->1->4->3.

分析

一、递归

  1. 我们假设链表只有三个结点,交换前两个结点。交换后,头结点应连向原来的第三个结点,第二个结点连向第一个结点,交换完成,第二个结点就是新的头结点了。但我们要先记下第二个结点,不然头结点连向了第三个结点,第二个结点就丢失了。

    public ListNode swapPairs(ListNode head) {
        ListNode newHead = head.next;
        head.next = head.next.next;
        newHead.next = head;
        return newHead;
    }
  2. 这样只是处理了一次,要递归处理,我们就先进入递归去处理最后面的结点,然后再一路返回。就是先把每次的第三个结点当作头结点进行处理。我们把head.next = head.next.next改成head.next = swapPairs(head.next.next)就可以了。

  3. 这样我们的操作其实就已经完成了,接下来就是判断递归终止的条件,两个结点以上才能交换,所以终止条件应是头结点为空,或头结点的下一结点为空。

    if (head == null || head.next == null) {
        return head;
    }

二、迭代

  1. 我们先定义一个哑结点 dumb,把它与头结点相连,并定义一个 pre 结点,pre 结点始终表示当前进行交换的第一个结点的上一个结点,起始时即 dumb。

    ListNode dumb = new ListNode(0), pre = dumb;
    dumb.next = head;
  2. 每次遍历,我们用 first 表示这次循环要交换的两个结点的第一个,second 表示第二个。像递归那样,我们还先假设链表只有三个结点,我们先把 first 连向第三个结点,second 连向 first,此时已交换了两个结点。

    ListNode first = pre.next;
    ListNode second = pre.next.next;
    first.next = second.next;
    second.next = first;
  3. 但此时前一个结点仍然连向 first,应连回 second,交换后的 second 才是前一个结点的下一个结点。pre 结点始终表示当前进行交换的第一个结点的上一个结点,此轮的两个结点已交换,准备下一轮,pre 应更新为第三个结点的上一个结点,即 first ,因为 first 和 second 已经完成了交换,此时 first 结点就是第二个结点。

    pre.next = second;
    pre = first;
  4. 循环进行的条件应该是当前进行交换的两个结点均不为空,即pre.next != null && pre.next.next != null

  5. 最后我们应该返回的是 dumb 的下一个结点 dumb.next。

代码

解法一:递归

class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = head.next;
        head.next = swapPairs(head.next.next);
        newHead.next = head;
        return newHead;
    }
}

解法二:迭代

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dumb = new ListNode(0), pre = dumb;
        dumb.next = head;
        while (pre.next != null && pre.next.next != null) {
            ListNode first = pre.next;
            ListNode second = pre.next.next;
            first.next = second.next;
            second.next = first;
            pre.next = second;
            pre = first;
        }
        return dumb.next;
    }
}

小结

个人觉得递归法很好理解,反而是迭代法有点绕,不过画一下图也就清楚了。

我发现,递归结束的条件和迭代进行的条件又是刚好相反。


原文地址:https://www.cnblogs.com/qiu_jiaqi/p/LeetCode_24.html