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

题目描述

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

示例 1:
交换链表

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

示例 2:

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

示例 3:

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

提示:

  • 链表中节点的数目在范围 [0, 100]
  • 0 <= Node.val <= 100

解题方法

方法一:数组存储

已知链表结点两两交换,那我们只需要提供两个 l i s t list list集合,分别按先后顺序存储交换后的结点。遍历链表时以 n u m num num计数( n u m num num初始为0),每遍历到一个结点,记录当前 n u m num num的奇偶性,当 n u m num num是偶数时,将当前结点添加到 l i s t 2 list2 list2中;若 n u m num num是奇数时,则将当前结点添加到 l i s t 1 list1 list1中。之后, n u m + + num++ num++。数组存储完成之后,我们按照先 l i s t 1 list1 list1的一个结点,再 l i s t 2 list2 list2的一个结点添加到最终链表的尾部。直到数组遍历完成,此时 l i s t 1 list1 list1的第一个结点即为交换后链表的头结点。

java代码

ListNode结构

public class ListNode {
    public int val;
    public ListNode next;

    public ListNode() {
    }

    public ListNode(int val) {
        this.val = val;
    }

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

结点交换方法

public ListNode swapPairs(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    List<ListNode> list1 = new ArrayList<>();
    List<ListNode> list2 = new ArrayList<>();
    int num = 0;
    ListNode curNode = head;
    while (curNode != null) {
        if (num % 2 == 0) {
            list2.add(curNode);
        } else {
            list1.add(curNode);
        }
        num++;
        curNode = curNode.next;
    }
    for (int i = 0; i < list1.size(); i++) {
        ListNode node = list1.get(i);
        node.next = list2.get(i);
        //list1没遍历到尾部
        if (i != list1.size() - 1) {
            //list1后面还有结点
            node.next.next = list1.get(i + 1);
        } else {
            //list2比list1多一个元素
            if (list2.size() > list1.size()) {
                //list2的最后一个元素是最后一个结点
                node.next.next = list2.get(i + 1);
            } else {
                //list1和list2元素一样多,list2最后一个结点的next指针指向null
                node.next.next = null;
            }
        }
    }
    return list1.get(0);
}

复杂度分析

时间复杂度:需要遍历一次链表,再遍历一次 l i s t list list数组,所以渐进时间复杂度为 O ( N ) O(N) O(N) N N N为链表长度。
空间复杂度: O ( N ) O(N) O(N)。需要用数组存储链表结点。

方法二:递归

我们还可以采用递归的方式构造交换链表。思路是在每次递归中,记 s w a p P a i r s swapPairs swapPairs方法中的参数 h e a d head head为第一个结点,第二个结点是 h e a d . n e x t head.next head.next,记为 n e w H e a d newHead newHead,第三个结点是 n e w H e a d . n e x t newHead.next newHead.next结点,记 n e x t H e a d nextHead nextHead结点。我们需要将 n e w H e a d newHead newHead变为第一个结点,并将 n e w H e a d . n e x t newHead.next newHead.next指向 h e a d head head,然后将 h e a d . n e x t head.next head.next结点指向 s w a p P a i r s ( n e x t H e a d ) swapPairs(nextHead) swapPairs(nextHead)返回的结点,最终返回参数为 n e w H e a d newHead newHead。终止条件是当 h e a d head head或者 h e a d . n e x t head.next head.next为空时,直接返回 h e a d head head

java代码

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

复杂度分析

时间复杂度:需要遍历一次链表,所以渐进时间复杂度为 O ( N ) O(N) O(N) N N N为链表长度。递归深度为 N / 2 N/2 N/2 N N N最大为100,深度最大为50,不会栈溢出。
空间复杂度: O ( N ) O(N) O(N)。空间复杂度主要取决于递归栈占用的空间。

方法三:迭代

为了减少递归栈占用的空间,我们也可以将递归改为迭代的方式。我们记遍历中原链表的第一个结点为 p r e N o d e preNode preNode p r e N o d e preNode preNode n e x t next next结点为第二个结点,记为 n o d e node node,第三个结点为 n o d e node node n e x t next next结点,记为 n e x t P r e N o d e nextPreNode nextPreNode。每次迭代中,如果 n e x t P r e N o d e nextPreNode nextPreNode n e x t P r e N o d e . n e x t nextPreNode.next nextPreNode.next存在,我们需要将 n o d e . n e x t node.next node.next指向 p r e N o d e preNode preNode p r e N o d e . n e x t preNode.next preNode.next指向 n e x t P r e N o d e . n e x t nextPreNode.next nextPreNode.next。再将 p r e N o d e preNode preNode指向 n e x t P r e N o d e nextPreNode nextPreNode n o d e node node指向 n e x t P r e N o d e . n e x t nextPreNode.next nextPreNode.next,进入下一次迭代。
若迭代中 n e x t P r e N o d e nextPreNode nextPreNode或者 n e x t P r e N o d e . n e x t nextPreNode.next nextPreNode.next不存在,则 n o d e . n e x t node.next node.next指向 p r e N o d e preNode preNode p r e N o d e . n e x t preNode.next preNode.next指向 n e x t P r e N o d e nextPreNode nextPreNode,然后跳出迭代。

java代码

public ListNode swapPairs2(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode newHead = head.next;
    ListNode node = newHead;
    ListNode preNode = head;
    while (true) {
        ListNode nextPreNode = node.next;
        node.next = preNode;
        //nextPreNode后面不再有结点
        if (nextPreNode == null || nextPreNode.next == null) {
            preNode.next = nextPreNode;
            break;
        }
        preNode.next = nextPreNode.next;
        preNode = nextPreNode;
        node = nextPreNode.next;
    }
    return newHead;
}

复杂度分析

时间复杂度:需要遍历一次链表,所以渐进时间复杂度为 O ( N ) O(N) O(N)
空间复杂度: O ( 1 ) O(1) O(1)。只有常数级别的指针存储。


  • 个人公众号
    个人公众号
  • 个人小游戏
    个人小游戏

相关推荐

  1. leetcode24. 交换节点

    2024-02-05 00:02:03       49 阅读
  2. LeetCode [24] 交换节点

    2024-02-05 00:02:03       44 阅读
  3. Leetcode24. 交换节点

    2024-02-05 00:02:03       44 阅读
  4. LeetCode24.交换节点

    2024-02-05 00:02:03       40 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-05 00:02:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-05 00:02:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-05 00:02:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-05 00:02:03       20 阅读

热门阅读

  1. 技术栈面试综合整理

    2024-02-05 00:02:03       34 阅读
  2. Liunx基本指令

    2024-02-05 00:02:03       28 阅读
  3. 利用tshark从pcap中解析http流量

    2024-02-05 00:02:03       34 阅读
  4. Linux系统内核-TCP连接数和网络等待时间设置优化

    2024-02-05 00:02:03       35 阅读
  5. 【设计模式:interpreter pattern】

    2024-02-05 00:02:03       30 阅读
  6. 【python3】多线程详解

    2024-02-05 00:02:03       29 阅读
  7. Tomcat(1)作用及自定义Tomcat实现

    2024-02-05 00:02:03       32 阅读
  8. Redis的过期键的删除策略

    2024-02-05 00:02:03       28 阅读
  9. Ubuntu权限相关命令

    2024-02-05 00:02:03       36 阅读
  10. 计算机网络(复习资料)

    2024-02-05 00:02:03       31 阅读
  11. 解决SpringBootAdmin部署到线上后无法访问

    2024-02-05 00:02:03       33 阅读