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


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

    题目描述

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

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

    示例 :

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

    链表定义如下:

    public class ListNode {
        int val;
        ListNode next;
    
        ListNode(int x) {
            val = x;
        }
    }
    

    分析与代码

    解法一:递归

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

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

    解法二:迭代

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

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

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

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

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

    代码:

    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;
        }
    }
    

    小结

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

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



    ┆ 然 ┆   ┆   ┆   ┆ 可 ┆   ┆   ┆ 等 ┆ 暖 ┆
    ┆ 而 ┆ 始 ┆   ┆   ┆ 是 ┆ 将 ┆   ┆ 你 ┆ 一 ┆
    ┆ 你 ┆ 终 ┆ 大 ┆   ┆ 我 ┆ 来 ┆   ┆ 如 ┆ 暖 ┆
    ┆ 没 ┆ 没 ┆ 雁 ┆   ┆ 在 ┆ 也 ┆   ┆ 试 ┆ 这 ┆
    ┆ 有 ┆ 有 ┆ 也 ┆   ┆ 这 ┆ 会 ┆   ┆ 探 ┆ 生 ┆
    ┆ 来 ┆ 来 ┆ 没 ┆   ┆ 里 ┆ 在 ┆   ┆ 般 ┆ 之 ┆
    ┆   ┆   ┆ 有 ┆   ┆   ┆ 这 ┆   ┆ 降 ┆ 凉 ┆
    ┆   ┆   ┆ 来 ┆   ┆   ┆ 里 ┆   ┆ 临 ┆ 薄 ┆
  • 相关阅读:
    [转]wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容) 实例介绍
    [转]HTTPS连接的前几毫秒发生了什么
    将生成的数据写入文件
    linux查看网络监听端口
    [转] Linux下移动virtualbox虚拟硬盘丢失eth0
    sockaddr结构体
    以十六进制形式打印字符串
    pta5-9 Huffman Codes (30分)
    pat1068. Find More Coins (30)
    hduoj 2955Robberies
  • 原文地址:https://www.cnblogs.com/qiu_jiaqi/p/LeetCode-24.html
Copyright © 2020-2023  润新知