📜  数据结构|链表|问题16(1)

📅  最后修改于: 2023-12-03 15:26:09.546000             🧑  作者: Mango

题目介绍:数据结构-链表-问题16

在链表中,给定一个头结点和两个整数m、n,需要将链表中第m个节点到第n个节点这部分进行反转。例如,给定 1->2->3->4->5->NULL,m=2 及 n=4,返回 1->4->3->2->5->NULL。

解题思路

遍历链表需用到指针操作,指针的操作主要有以下几种:

  1. 将指针指向链表头部。

  2. 判断当前指针是否为空:如果为空,则可能存在链表为空,也可以到了链表末尾。

  3. 遍历链表中的节点:得到当前节点,校验当前节点是否进行反转,如果当前节点需要反转,则将当前节点加入反转链表并遍历下一个节点,如果当前节点不需要反转,则不将当前节点加入反转链表,直接遍历下一个节点。

  4. 反转链表:在遍历完所需反转的连续几个节点之后,将反转链表进行反转。

  5. 将反转链表加入原始链表中:反转后,将反转链表的头指针与第m节点的前一个节点的指针相连接,将第n个节点的指针与反转链表的尾指针相连接即可。

代码实现

public ListNode reverseBetween(ListNode head, int m, int n) {
    if (head == null) {
        return null;
    }
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode pre = dummy;
    for (int i = 1; i < m; i++) {
        pre = pre.next;
    }
    ListNode cur = pre.next;
    for (int i = m; i < n; i++) {
        ListNode next = cur.next;
        cur.next = next.next;
        next.next = pre.next;
        pre.next = next;
    }
    return dummy.next;
}

在本题中,我们需要遍历整个链表,因此需要用到两个指针:一个指向当前节点的前一个节点,另一个指向当前节点。

从头开始遍历链表:使用pre指针和cur指针,将pre指针指向目标节点的前一个节点,将cur指针指向当前节点。然后不断遍历到目标节点的结束位置。

将遍历过的节点进行反转:使用next指针记录当前节点的下一个节点,然后将当前节点的next指向之前反转节点的前一个节点,接着将之前反转节点的前一个节点的next指向当前节点。将pre指针指向当前节点,cur指针指向下一个节点。

返回整个链表的头结点即可。

时间复杂度

该算法的时间复杂度为 O(n),其中 n 是链表的长度。在遍历链表一次后,最多可反转链表中的 n 个节点。

空间复杂度

该算法的空间复杂度为 O(1),因为只使用了常数个额外的变量。